package com.tuhui.service;

import com.tuhui.util.ConstantUtil;
import com.tuhui.util.FileUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import sun.misc.BASE64Encoder;

import java.io.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@Slf4j
public class AckSenderService{

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Value("${file.path}")
    private String filePath;

    //不可路由的信息返回
    final  RabbitTemplate.ReturnCallback returnCallback = new RabbitTemplate.ReturnCallback() {
        @Override
        public void returnedMessage(Message message, int i, String s, String s1, String s2) {
            try {
                //如果是对象
                if(message.getMessageProperties().getContentType().equals("application/x-java-serialized-object")){
                    //read object from stream 反序列化将stream生成Object对象
                    ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(message.getBody()));
                    Map map = (Map)ois.readObject();
                    if(map.get("path")!=null){
                        ConstantUtil.FileErrorMap.put(map.get("path").toString(),map.get("path"));
                    }
                    log.info("失败的信息："+map.toString());
                }
            } catch (IOException e) {
                log.error("调用returnedMessage解析数据失败:{}",e);
            } catch (ClassNotFoundException e) {
                log.error("调用returnedMessage读取流失败:{}",e);
            }
        }
    };

    //回调函数: confirm确认
    final RabbitTemplate.ConfirmCallback confirmCallback = new RabbitTemplate.ConfirmCallback() {
        @Override
        public void confirm(CorrelationData correlationData, boolean ack, String cause) {
            String messageId = correlationData.getId();
            if(ack){
                //删除错误的记录
                if(ConstantUtil.FileErrorMap.get(messageId)!=null && !ConstantUtil.FileErrorMap.get(messageId).equals("")){
                    ConstantUtil.FileErrorMap.remove(messageId);
                }
                ConstantUtil.FileSuccessList.add(messageId);
                log.info("信息投递成功！correlationData：{} ===ack{}====cause:{}",correlationData,ack,cause);
            } else {
                //失败则进行具体的后续操作:重试 或者补偿等手段
                log.error("信息投递失败：correlationData：{},ack:{},cause:{}",correlationData,ack,cause);
            }
        }
    };

    /**
     * 消息发送
     */
    public void send() {
        try{
            List<File> fileList = FileUtil.getFiles(filePath);
            fileList.forEach(file -> {
                BASE64Encoder encoder = new BASE64Encoder();// 创建BASE64Encoder编码实例
                String content = null;
                Map map = new HashMap<String,Object>();
                map.put("path",file.getPath());
                log.info("发送的文件地址：{}",file.getPath());
                InputStream inputStream = null;
                try {
                    inputStream = new FileInputStream(file);
                    byte[] data = new byte[inputStream.available()];
                    inputStream.read(data);
                    content = encoder.encode(data);// 编码文件 得到String
                } catch (Exception e) {
                    log.error("error:循环读取读取文件失败{}",e);
                }finally {
                    if(inputStream!=null){
                        try {
                            inputStream.close();
                        } catch (IOException e) {
                            log.error("关闭流异常：{}",e);
                        }
                    }
                }
                map.put("file",content);
                //设置返回回调
                rabbitTemplate.setReturnCallback(returnCallback);
                //设置确认回调
                rabbitTemplate.setConfirmCallback(confirmCallback);
                CorrelationData correlationData = new CorrelationData();
                correlationData.setId(file.getPath());
                //不发送重复的数据
                if(ConstantUtil.FileSuccessList.indexOf(file.getPath().toString())==-1){
                    rabbitTemplate.convertAndSend("fanoutExchange","",map,correlationData);
                    log.info("发送的文件地址：{} 成功",file.getPath());
                }
            });
        }catch (Exception e){
            log.error("error:发送mq消息异常{}",e);
        }
    }

    /**
     * 删除文件
     */
    public void deleteFile(){
            log.info("要删除的文件有多少{}个",ConstantUtil.FileSuccessList.size());
            if(ConstantUtil.FileSuccessList!=null && ConstantUtil.FileSuccessList.size()>0){
                for(int i=0;i<ConstantUtil.FileSuccessList.size();i++) {
                    String path = ConstantUtil.FileSuccessList.get(i);
                    if (ConstantUtil.FileErrorMap.get(path) == null || ConstantUtil.FileErrorMap.get(path).equals("")) {
                        new File(path).delete();
                        ConstantUtil.FileSuccessList.remove(i);
                        log.info("删除文件成功：{}", path);
                    }
                }
            }
    }
}